home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 27 / CU Amiga Magazine's Super CD-ROM 27 (1998)(EMAP Images)(GB)[!][issue 1998-10].iso / CUCD / Programming / Yaroze / UploadSrc / upload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-12-08  |  10.0 KB  |  391 lines

  1. /*
  2.  * NAME
  3.  *   upload.c - 17-Apr-97 16:40:52
  4.  *
  5.  * AUTHOR
  6.  *   Jon Rocatis - jon@funcom.com
  7.  *
  8.  * DESCRIPTION
  9.  *   Yaroze Upload tool. Reads batch files and executes them.
  10.  *   Not all commands are supported at the moment!
  11.  *
  12.  */
  13.  
  14. #include <ctype.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <exec/types.h>
  18. #include <devices/serial.h>
  19. #include <proto/all.h>
  20. #include <time.h>
  21. #include <string.h>
  22.  
  23. #include "upload_protos.h"
  24. #include "serial_protos.h"
  25. #include "tools_protos.h"
  26. #include "parse_protos.h"
  27. #include "myecoff.h"
  28. #include "upload.h"
  29.  
  30. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  31.  
  32. // Endian change for 32 bit integers
  33. #define ENDIAN_CHG32(a) ( ((a >> 24) & 0xff) | ((a >> 8) & 0xff00) | ((a << 8) & 0x00ff0000) | ((a << 24) & 0xff000000) ) 
  34.  
  35. // Endian change for 16 bit integers
  36. #define ENDIAN_CHG16(a) ( ((a >> 8) & 0xff) | ((a << 8) & 0xff00) )
  37.  
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  39.  
  40. VERSTRING;       // Amiga program version string
  41.  
  42. LONG jumpAddr;   // The start address of the executable
  43.  
  44. BOOL dontSendData;
  45. int baudRate;
  46.  
  47. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  48.  
  49. /*
  50.  * NAME
  51.  *   SendGo
  52.  *
  53.  * FUNCTION
  54.  *   Sends the "go" command to the PlayStation. First sets the EPC register.
  55.  *
  56.  * INFO
  57.  *   When uploading COFF file:
  58.  *     REG_EPC must be set to a_entry
  59.  *     REG_GP must be set to a_gp
  60.  *     REG_SP must be set to 0x801fff00
  61.  *
  62.  */
  63.  
  64. void SendGo( void )
  65. {
  66.   UBYTE dynacmd[100];
  67.   LONG  cmdlen;
  68.  
  69.     printf( "Here we go!\n" );
  70.     printf( "Jump address: $%08x\n\n", jumpAddr );
  71.  
  72.     cmdlen = sprintf( dynacmd, "sr epc %08x\015", jumpAddr);
  73.     SerialSend( dynacmd, cmdlen );
  74.     Wait( SIGBREAKF_CTRL_D );
  75.     cmdlen = sprintf( dynacmd, "go\015", jumpAddr);
  76.     SerialSend( dynacmd, cmdlen );
  77. }
  78.  
  79. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  80.  
  81. /*
  82.  * NAME
  83.  *   DataSend
  84.  *
  85.  * FUNCTION
  86.  *   Uploads a binary file to the PlayStation.
  87.  *
  88.  * INPUT
  89.  *   fh - file ptr to already opened binary file (ready to read)
  90.  *   loadAddr - the load address of the file
  91.  *   size - the size in bytes of the file
  92.  *
  93.  */
  94.  
  95. void DataSend( const BPTR fh, const ULONG loadAddr, const ULONG size )
  96. {
  97.   struct UploadHeader ulh; // Header that request file uploading on PSX
  98.   struct Packet *packet;   // Ptr to packet that is send to PSX
  99.   ULONG  sigs;             // Signal mask received from Wait()
  100.   LONG   rest,             // #bytes still left to be send from file
  101.          rlen;             // #bytes still left to be send from buffer
  102.  
  103.   static UBYTE cmd1[] = {'b','w','r',0x0d};      // "Binary Write" command
  104.   static UBYTE cmd2[] = {0x0d};
  105.  
  106.     packet = AllocMem( sizeof(struct Packet), 0 );
  107.     if ( packet == NULL )
  108.       return;
  109.  
  110.     printf( "Starting upload.. " );
  111.     fflush( stdout );
  112.       
  113.     SerialSend( cmd1, sizeof(cmd1) );        // Tell PSX we want to upload.. (The PSX will answer with: "bwr" 0x0a 0x0d "binary" 0x0d)
  114.  
  115.     //
  116.     
  117.     w4bin = TRUE;
  118. //    printf( "Waiting for 'bwr binary' (with auto) \n" );
  119.     sigs = Wait( SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_D );
  120.     w4bin = FALSE;
  121.     
  122.     if ( sigs & SIGBREAKF_CTRL_C )
  123.       goto stop;
  124.       
  125.     if ( sigs & SIGBREAKF_CTRL_D )
  126.     {
  127.       // Got 'bwr binary' automatically
  128.       Delay( 5 );
  129.     }
  130.       
  131.     //
  132.       
  133.     packet->id = STATE_DATA;
  134.        
  135.     ulh.id      = STATE_UPLOAD;
  136.     ulh.address = loadAddr;
  137.     ulh.length  = size;
  138.     SerialSend( &ulh.id, 9 );           // Tell PSX load address and size of file to upload (PSX doesn't answer this one it seems!)
  139.  
  140.     Delay( 20 );
  141.  
  142.     // Now lets send the data in 2K chunks..
  143.     
  144.     for ( rest = size; rest > 0; )
  145.     {
  146.       UBYTE chksum;
  147.       LONG  cidx;
  148.       
  149.       if ( rest >= BLOCKSIZE )
  150.         rlen = BLOCKSIZE;
  151.       else
  152.       {
  153.         rlen = rest;
  154.         memset( &packet->data, 0, sizeof(packet->data) );
  155.       }
  156.       Read( fh, &packet->data, rlen );
  157.  
  158.       printf( "\r  (%6d / %6d) %d%%.. ", (size - rest), size, 100 - (rest*100 / size));
  159.       fflush( stdout );
  160.       
  161.       rest -= rlen;
  162.       
  163. //      printf( "rlen = %d, rest = %d\n", rlen, rest );
  164.  
  165.       for ( chksum = cidx = 0; cidx < BLOCKSIZE; cidx++ )
  166.         chksum += packet->data[cidx];
  167.  
  168.       packet->chksum = chksum;  
  169. //      printf( "Chksum = %02x\n", chksum );
  170.  
  171. //      Wait( SIGBREAKF_CTRL_F );
  172.       Delay(7);                          // 7 seems to be the lowest!
  173.       
  174.     retry:     
  175.       w4y = TRUE;
  176.       SerialSend( packet, sizeof(struct Packet) );
  177. //      printf("Waiting for 'Y' (CF)\n");
  178.       sigs = Wait( SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F );
  179.       if ( sigs & SIGBREAKF_CTRL_E )
  180.       {
  181. //        printf( "Got Y!\n");
  182.       }
  183.       else
  184.       {
  185.         if ( sigs & SIGBREAKF_CTRL_F )
  186.           goto retry;
  187.         else
  188.           goto stop;
  189.       }
  190. //      Delay(7);                          // 7 seems to be the lowest!
  191.     }
  192.  
  193.     printf( "\rUploaded %d bytes       \n", size );
  194.     fflush( stdout );
  195.  
  196.     // The whole file has been transferred! Now wait for the PSX to be ready again for more.
  197.     
  198.     SerialSend( cmd2, 1 );
  199. //    printf( "Waiting for '>>'\n" );
  200.     sigs = Wait( SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_D );
  201.     if ( sigs & SIGBREAKF_CTRL_C )
  202.       goto stop;
  203.     if ( sigs & SIGBREAKF_CTRL_D )
  204.     {
  205. //      printf( "Got >>\n" );
  206.     }
  207. //    printf( "\n\n" );
  208.  
  209.   stop:
  210.     FreeMem( packet, sizeof(struct Packet) );
  211. }
  212.  
  213. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  214.  
  215. /*
  216.  * NAME
  217.  *   WaitForPSX
  218.  *
  219.  * FUNCTION
  220.  *   Waits for the PSX to send '>>'
  221.  *
  222.  */
  223.  
  224. void WaitForPSX( void )
  225. {
  226.   static UBYTE cmd2[] = {0x0d};
  227.  
  228.     printf( "All data transfered! (F). " );
  229.     fflush( stdout );
  230.     SerialSend( cmd2, 1 );
  231.     Wait( SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_F );
  232.     printf( "Got >>..\n\n" );
  233. }
  234.  
  235. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  236.  
  237. /*
  238.  * NAME
  239.  *   UploadExe
  240.  *
  241.  * FUNCTION
  242.  *   Uploads a PlayStation executable. Searches the COFF file and extracts
  243.  *   info on the 4 needed sections (text, rdata, data, sdata)
  244.  *
  245.  * INPUT
  246.  *   fname - ptr to filename
  247.  *
  248.  * RESULT
  249.  *   An uploaded file or error message if anything went wrong
  250.  *
  251.  */
  252.  
  253. #define FAIL(a) { puts(a); goto error; }
  254.  
  255. void UploadExe( char *fname )
  256. {
  257.   LONG    idx, totSize, numSects;
  258.   struct  Section *sections = NULL;
  259.   struct  ecoff_file_hdr header;
  260.   struct  ecoff_aout_hdr aheader;
  261.   BPTR    fh;
  262.  
  263.     printf( "Program load!\n" );
  264.   
  265.     fh = Open( fname, MODE_OLDFILE );
  266.     if (!fh)
  267.       FAIL( "Couldn't open file!\n" );
  268.  
  269.     printf( "Reading %s..\n", fname );
  270.     Read( fh, &header, sizeof(header) );
  271.     if ( header.f_magic != ECOFF_MIPS_MAGIC_LITTLE_SWAP )
  272.       FAIL( "Not a Yaroze EXE file!\n" );
  273.  
  274.     numSects = ENDIAN_CHG16( header.f_nscns );
  275.     sections = AllocVec( sizeof(struct Section) * numSects, 0 );
  276.     if ( sections == NULL )
  277.       FAIL( "Out of memory!\n" );
  278.  
  279.     //
  280.  
  281.     Read( fh, &aheader, sizeof(aheader) );
  282.     jumpAddr = ENDIAN_CHG32( aheader.a_entry );
  283.     printf( "Jump address: $%08x\n\n", jumpAddr );
  284.  
  285.     //
  286.  
  287.     Read( fh, sections, sizeof(struct Section) * numSects );
  288.  
  289.     for ( totSize = idx = 0; idx < 4 /*numSects*/; idx++ )
  290.     {
  291.       sections[idx].loadAddr = ENDIAN_CHG32( sections[idx].loadAddr );
  292.       sections[idx].size     = ENDIAN_CHG32( sections[idx].size );
  293.       sections[idx].fpos     = ENDIAN_CHG32( sections[idx].fpos );
  294.       DisplaySectionInfo( §ions[idx] );
  295.       totSize += sections[idx].size;
  296.     }
  297.     printf( "Total size of sections: %d bytes (%dK)\n\n", totSize, ((totSize-1) / 1024) + 1 );
  298.  
  299.     ///////
  300.  
  301.     for ( idx = 0; idx < 4; idx++ )             // Send 4 sections
  302.     {
  303.       Seek( fh, sections[idx].fpos, OFFSET_BEGINNING );
  304.       DataSend( fh, sections[idx].loadAddr, sections[idx].size );
  305.     }
  306.     WaitForPSX();
  307.     
  308.     ///////
  309.     
  310.   error:
  311.     if (sections) FreeVec(sections);
  312.     if (fh) Close(fh);
  313. }
  314.  
  315. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  316.  
  317. BYTE printSigNum; 
  318.  
  319. void main( int argc, char **argv )
  320. {
  321.   char *fname;
  322.   FILE *fp;
  323. //  static char test[4] = {0x1,0x2,0x3,0x4};
  324.   
  325.     printSigNum = AllocSignal(-1);
  326.   
  327.     if ( (argc < 2) || (argc > 3) )
  328.     {
  329.       printf( "Usage: %s <batchfile> [nd]\n", argv[0] );
  330.       exit(1);
  331.     }
  332.  
  333.     fname = argv[1];
  334.     if (!(fp = fopen( fname, "r" )))
  335.     {
  336.       printf( "*** Couldn't open %s!\n", fname );
  337.       exit(1);
  338.     }
  339.     
  340.     if ( argc == 3 )
  341.       dontSendData = TRUE; 
  342.     else  
  343.       dontSendData = FALSE; 
  344.  
  345.     baudRate = GetBaudRate();
  346.     if (baudRate == -1)
  347.     {
  348.       printf( "*** Illegal baudrate!\n" );
  349.       exit(1);
  350.     }
  351.       
  352.     if ( SerialInit() )
  353.     {
  354.       if ( InitTask() )
  355.       {
  356.         LONG sigs;
  357.         
  358.         printf( "\nParsing '%s'. Baud rate: %d\n\n", fname, baudRate );
  359.         ParseBatchFile( fp );
  360.         printf( "Parsing complete. Press CTRL-F to quit\n" );
  361.         
  362.         Signal( task, SIGBREAKF_CTRL_E );
  363.         do
  364.         {
  365.           sigs = Wait( SIGBREAKF_CTRL_F | SIGBREAKF_CTRL_D | (1L << printSigNum) );
  366.           if (sigs & (1L << printSigNum))
  367.             PrintLine();
  368. /*          
  369.           if (sigs & SIGBREAKF_CTRL_D)
  370.           {
  371.             printf(">> sending\n");
  372.             SerialSend( test, 4 );
  373.           }  
  374. */          
  375.         } while (!(sigs & SIGBREAKF_CTRL_F));
  376.         
  377.         FreeTask();
  378.       }
  379.       else
  380.         printf( "*** Couldn't Initialize Task!\n" );
  381.  
  382.       SerialClose();
  383.     } 
  384.     else
  385.       printf( "*** Couldn't Initialize Serial Device!\n" );
  386.  
  387.     fclose( fp );
  388. }
  389.  
  390. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  391.